package util;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.List;

import model.Estado;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.Example.PropertySelector;
import org.hibernate.criterion.MatchMode;
import org.hibernate.type.Type;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import sun.awt.geom.AreaOp.AddOp;

public abstract class HibernateDAO<T, PK extends Serializable> 
	extends HibernateDaoSupport 
	implements GenericDAO<T, PK>, PropertySelector {

	private Class objectClass;
    private static Log LOG = LogFactory.getLog(HibernateDAO.class);  


	public HibernateDAO(Class clazz) {
		this.objectClass = clazz;
	}
	
	public T save(T entity) {
		try {
			
			this.getHibernateTemplate().save(entity);
			
			
			return entity;
		
		} catch (HibernateException e) {
			this.logger.error(e);
			throw convertHibernateAccessException(e);
		}		
	}
	
	public T update(T entity) {
		try {
			this.getHibernateTemplate().update(entity);
			this.getHibernateTemplate().flush();
			return entity;
		
		} catch (HibernateException e) {
			this.logger.error(e);
			throw convertHibernateAccessException(e);
		}	
	}
	public T findOneByExample(T example) {
		try {
			return (T) this.getHibernateTemplate().getSessionFactory().getCurrentSession().createCriteria(objectClass)
					.add(Example.create(example).enableLike(MatchMode.START)).uniqueResult();
		
		} catch (HibernateException e) {
			this.logger.error(e);
			throw convertHibernateAccessException(e);
		}		
	};
	
	@Override
	public List<T> getAll() {
		try {
			List<T> list = (List<T>)this.getHibernateTemplate().loadAll(objectClass);
			return list;
			
		} catch (HibernateException e) {
			this.logger.error(e);
			throw convertHibernateAccessException(e);
		}	
	}
	
	public void delete(T entity) {
		try {
			this.getHibernateTemplate().delete(entity);
			this.getHibernateTemplate().flush();
		
		} catch (HibernateException e) {
			this.logger.error(e);
			throw convertHibernateAccessException(e);
		}		
	}
	
	public T get(PK id) {
		try {
			final Session s = getSession(false);
			return (T) s.load(getObjectClass(), id);		
		
		} catch (HibernateException e) {
			this.logger.error(e);
			throw convertHibernateAccessException(e);
		}		
	}
	
	public List<T> findByExample(T example) {
		try {
			return this.getHibernateTemplate().getSessionFactory().getCurrentSession().createCriteria(objectClass)
				.add(Example.create(example).enableLike(MatchMode.ANYWHERE)).list();
			
		
		} catch (HibernateException e) {
			this.logger.error(e);
			throw convertHibernateAccessException(e);
		}		
	}
	
	public List<T> findByExample(T example, int first, int max) {
		try {
			Criteria criteria = this.getHibernateTemplate().getSessionFactory().getCurrentSession().createCriteria(objectClass)
				.add(Example.create(example).enableLike(MatchMode.ANYWHERE));
			
			if (first != 0) {
                criteria.setFirstResult(first);
            }
            if (max != 0) {
                criteria.setMaxResults(max);
            }
			return criteria.list();
		
		} catch (HibernateException e) {
			this.logger.error(e);
			throw convertHibernateAccessException(e);
		}	
	}
	
	@Override
	public boolean include(Object arg0, String arg1, Type arg2) {
		// TODO Auto-generated method stub
		return false;
	}
	
	@Override
	public Class getObjectClass() {
		return objectClass;
	}
	
}
